#include "Common.h"
#include "bcos-codec/abi/ContractABICodec.h"
#include <chrono>

constexpr static std::string_view HELLOWORLD_BYTECODE =
    "608060405234801561001057600080fd5b50611621806100206000396000f3fe608060405234801561001057600080"
    "fd5b50600436106100cf5760003560e01c8063805e3da01161008c578063e3d670d711610066578063e3d670d71461"
    "01b4578063e5175c58146101e4578063f28a3b6514610214578063fd8f59071461021e576100cf565b8063805e3da0"
    "1461015a57806389ea642f14610178578063dcdb78bc14610196576100cf565b8063077142e4146100d457806321cd"
    "e8c7146100de5780634be422ae146100fa5780636273899814610104578063747586b8146101225780637fcaf66614"
    "61013e575b600080fd5b6100dc61023a565b005b6100f860048036038101906100f39190610840565b6102d0565b00"
    "5b61010261032a565b005b61010c610368565b604051610119919061088f565b60405180910390f35b61013c600480"
    "360381019061013791906108aa565b610371565b005b61015860048036038101906101539190610a1d565b61037b56"
    "5b005b61016261038e565b60405161016f919061088f565b60405180910390f35b6101806103a7565b60405161018d"
    "9190610ae5565b60405180910390f35b61019e610439565b6040516101ab919061088f565b60405180910390f35b61"
    "01ce60048036038101906101c99190610b07565b610448565b6040516101db919061088f565b60405180910390f35b"
    "6101fe60048036038101906101f991906108aa565b610491565b60405161020b919061088f565b60405180910390f3"
    "5b61021c6105a1565b005b61023860048036038101906102339190610b34565b6106cd565b005b6000604051610248"
    "9061077e565b604051809103906000f080158015610264573d6000803e3d6000fd5b50905060006040516102759061"
    "077e565b604051809103906000f080158015610291573d6000803e3d6000fd5b5090508073ffffffffffffffffffff"
    "ffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036102cc57600080fd5b505056"
    "5b80600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffff"
    "ffffff168152602001908152602001600020600082825461031f9190610bb6565b925050819055505050565b7f6270"
    "f0e0872f361f9d11ecd5fab7c94bc564ebe8a9e17a85b2d5cd9423a6e564600054600160405161035e929190610cf3"
    "565b60405180910390a1565b60008054905090565b8060008190555050565b806001908161038a9190610ec4565b50"
    "50565b60006103ed60008190555060006103a457600080fd5b90565b6060600180546103b690610c29565b80601f01"
    "602080910402602001604051908101604052809291908181526020018280546103e290610c29565b801561042f5780"
    "601f106104045761010080835404028352916020019161042f565b820191906000526020600020905b815481529060"
    "01019060200180831161041257829003601f168201915b5050505050905090565b60006103ee6000819055600080fd"
    "5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffff"
    "ffffffff168152602001908152602001600020549050919050565b6000806040516104a09061077e565b6040518091"
    "03906000f0801580156104bc573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffff"
    "ff1663e5c19b2d846040518263ffffffff1660e01b81526004016104f8919061088f565b6000604051808303816000"
    "87803b15801561051257600080fd5b505af1158015610526573d6000803e3d6000fd5b505050508073ffffffffffff"
    "ffffffffffffffffffffffffffff16636d4ce63c6040518163ffffffff1660e01b8152600401602060405180830381"
    "865afa158015610575573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061"
    "05999190610fab565b915050919050565b60006040516105af9061078b565b604051809103906000f0801580156105"
    "cb573d6000803e3d6000fd5b5090506000819050600060608273ffffffffffffffffffffffffffffffffffffffff16"
    "6040516024016040516020818303038152906040527fb0bea725000000000000000000000000000000000000000000"
    "000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffff"
    "ffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161067e91906110"
    "1f565b600060405180830381855af49150503d80600081146106b9576040519150601f19603f3d011682016040523d"
    "82523d6000602084013e6106be565b606091505b50809250819350505050505050565b80600260008573ffffffffff"
    "ffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260"
    "2001600020600082825461071c9190611036565b9250508190555080600260008473ffffffffffffffffffffffffff"
    "ffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082"
    "82546107729190610bb6565b92505081905550505050565b6101708061107a83390190565b610402806111ea833901"
    "90565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82"
    "169050919050565b60006107d7826107ac565b9050919050565b6107e7816107cc565b81146107f257600080fd5b50"
    "565b600081359050610804816107de565b92915050565b6000819050919050565b61081d8161080a565b8114610828"
    "57600080fd5b50565b60008135905061083a81610814565b92915050565b6000806040838503121561085757610856"
    "6107a2565b5b6000610865858286016107f5565b92505060206108768582860161082b565b9150509250929050565b"
    "6108898161080a565b82525050565b60006020820190506108a46000830184610880565b92915050565b6000602082"
    "840312156108c0576108bf6107a2565b5b60006108ce8482850161082b565b91505092915050565b600080fd5b6000"
    "80fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000"
    "000000000000600052604160045260246000fd5b61092a826108e1565b810181811067ffffffffffffffff82111715"
    "610949576109486108f2565b5b80604052505050565b600061095c610798565b90506109688282610921565b919050"
    "565b600067ffffffffffffffff821115610988576109876108f2565b5b610991826108e1565b905060208101905091"
    "9050565b82818337600083830152505050565b60006109c06109bb8461096d565b610952565b905082815260208101"
    "8484840111156109dc576109db6108dc565b5b6109e784828561099e565b509392505050565b600082601f83011261"
    "0a0457610a036108d7565b5b8135610a148482602086016109ad565b91505092915050565b60006020828403121561"
    "0a3357610a326107a2565b5b600082013567ffffffffffffffff811115610a5157610a506107a7565b5b610a5d8482"
    "85016109ef565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b"
    "83811015610aa0578082015181840152602081019050610a85565b60008484015250505050565b6000610ab782610a"
    "66565b610ac18185610a71565b9350610ad1818560208601610a82565b610ada816108e1565b840191505092915050"
    "565b60006020820190508181036000830152610aff8184610aac565b905092915050565b600060208284031215610b"
    "1d57610b1c6107a2565b5b6000610b2b848285016107f5565b91505092915050565b60008060006060848603121561"
    "0b4d57610b4c6107a2565b5b6000610b5b868287016107f5565b9350506020610b6c868287016107f5565b92505060"
    "40610b7d8682870161082b565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000"
    "000000000000000000600052601160045260246000fd5b6000610bc18261080a565b9150610bcc8361080a565b9250"
    "82820190508281121560008312168382126000841215161715610bf457610bf3610b87565b5b92915050565b7f4e48"
    "7b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060"
    "02820490506001821680610c4157607f821691505b602082108103610c5457610c53610bfa565b5b50919050565b60"
    "008190508160005260206000209050919050565b60008154610c7c81610c29565b610c868186610a71565b94506001"
    "821660008114610ca15760018114610cb757610cea565b60ff198316865281151560200286019350610cea565b610c"
    "c085610c5a565b60005b83811015610ce257815481890152600182019150602081019050610cc3565b808801955050"
    "505b50505092915050565b6000604082019050610d086000830185610880565b8181036020830152610d1a8184610c"
    "6f565b90509392505050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302"
    "610d707fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610d33565b610d7a8683"
    "610d33565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050"
    "565b6000610dc1610dbc610db784610d92565b610d9c565b610d92565b9050919050565b6000819050919050565b61"
    "0ddb83610da6565b610def610de782610dc8565b848454610d40565b825550505050565b600090565b610e04610df7"
    "565b610e0f818484610dd2565b505050565b5b81811015610e3357610e28600082610dfc565b600181019050610e15"
    "565b5050565b601f821115610e7857610e4981610c5a565b610e5284610d23565b81016020851015610e6157819050"
    "5b610e75610e6d85610d23565b830182610e14565b50505b505050565b600082821c905092915050565b6000610e9b"
    "60001984600802610e7d565b1980831691505092915050565b6000610eb48383610e8a565b91508260020282179050"
    "92915050565b610ecd82610a66565b67ffffffffffffffff811115610ee657610ee56108f2565b5b610ef08254610c"
    "29565b610efb828285610e37565b600060209050601f831160018114610f2e5760008415610f1c578287015190505b"
    "610f268582610ea8565b865550610f8e565b601f198416610f3c86610c5a565b60005b82811015610f645784890151"
    "8255600182019150602085019450602081019050610f3f565b86831015610f815784890151610f7d601f891682610e"
    "8a565b8355505b6001600288020188555050505b505050505050565b600081519050610fa581610814565b92915050"
    "565b600060208284031215610fc157610fc06107a2565b5b6000610fcf84828501610f96565b91505092915050565b"
    "600081519050919050565b600081905092915050565b6000610ff982610fd8565b6110038185610fe3565b93506110"
    "13818560208601610a82565b80840191505092915050565b600061102b8284610fee565b915081905092915050565b"
    "60006110418261080a565b915061104c8361080a565b92508282039050818112600084121682821360008512151617"
    "1561107357611072610b87565b5b9291505056fe608060405234801561001057600080fd5b50610150806100206000"
    "396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636d4ce63c1461003b"
    "578063e5c19b2d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f3"
    "5b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b806000819055505056"
    "5b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b"
    "92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1"
    "565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b915050"
    "9291505056fea26469706673582212203923e3590a4af8ad41941288c173be668ec096c4a41369abdf8da12cfd5751"
    "5564736f6c63430008120033608060405234801561001057600080fd5b506103e2806100206000396000f3fe608060"
    "405234801561001057600080fd5b506004361061002b5760003560e01c8063b0bea72514610030575b600080fd5b61"
    "003861003a565b005b614da46000819055506040518060400160405280600381526020017f68692100000000000000"
    "000000000000000000000000000000000000000000008152506001908161008791906102da565b50565b6000815190"
    "50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000006000526041600452"
    "60246000fd5b7f4e487b71000000000000000000000000000000000000000000000000000000006000526022600452"
    "60246000fd5b6000600282049050600182168061010b57607f821691505b60208210810361011e5761011d6100c456"
    "5b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b6000"
    "82821b905092915050565b6000600883026101867fffffffffffffffffffffffffffffffffffffffffffffffffffff"
    "ffffffffffff82610149565b6101908683610149565b95508019841693508086168417925050509392505050565b60"
    "00819050919050565b6000819050919050565b60006101d76101d26101cd846101a8565b6101b2565b6101a8565b90"
    "50919050565b6000819050919050565b6101f1836101bc565b6102056101fd826101de565b848454610156565b8255"
    "50505050565b600090565b61021a61020d565b6102258184846101e8565b505050565b5b818110156102495761023e"
    "600082610212565b60018101905061022b565b5050565b601f82111561028e5761025f81610124565b610268846101"
    "39565b81016020851015610277578190505b61028b61028385610139565b83018261022a565b50505b505050565b60"
    "0082821c905092915050565b60006102b160001984600802610293565b1980831691505092915050565b60006102ca"
    "83836102a0565b9150826002028217905092915050565b6102e38261008a565b67ffffffffffffffff8111156102fc"
    "576102fb610095565b5b61030682546100f3565b61031182828561024d565b600060209050601f8311600181146103"
    "445760008415610332578287015190505b61033c85826102be565b8655506103a4565b601f19841661035286610124"
    "565b60005b8281101561037a57848901518255600182019150602085019450602081019050610355565b8683101561"
    "03975784890151610393601f8916826102a0565b8355505b6001600288020188555050505b50505050505056fea264"
    "6970667358221220fa853e743e1e2a844a7a788534a46c2dce6fbff27bef6a64ac3c15c67549f2e164736f6c634300"
    "08120033a26469706673582212207f4fa2554331e8c5ef4917fea82fc88828584fb34b5f7a57d6d48d7b832d5cf564"
    "736f6c63430008120033";

constexpr static std::string_view HELLOWORLD_ABI =
    "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int256\",\"name\":"
    "\"value1\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":"
    "\"value2\",\"type\":\"string\"}],\"name\":\"EventExample\",\"type\":\"event\"},{"
    "\"conflictFields\":[{\"kind\":3,\"slot\":2,\"value\":[0]}],\"inputs\":[{\"internalType\":"
    "\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"balance\",\"outputs\":[{"
    "\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"selector\":[3822481623,"
    "2638755045],\"stateMutability\":\"view\",\"type\":\"function\"},{\"conflictFields\":[{"
    "\"kind\":0}],\"inputs\":[],\"name\":\"createTwice\",\"outputs\":[],\"selector\":[124863204,"
    "402369018],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"conflictFields\":[{"
    "\"kind\":0}],\"inputs\":[],\"name\":\"delegateCall\",\"outputs\":[],\"selector\":[4069145445,"
    "778625272],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"conflictFields\":[{"
    "\"kind\":0}],\"inputs\":[{\"internalType\":\"int256\",\"name\":\"value\",\"type\":\"int256\"}]"
    ",\"name\":\"deployAndCall\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":"
    "\"int256\"}],\"selector\":[3843513432,2945246509],\"stateMutability\":\"nonpayable\",\"type\":"
    "\"function\"},{\"conflictFields\":[{\"kind\":4,\"value\":[0]}],\"inputs\":[],\"name\":"
    "\"getInt\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],"
    "\"selector\":[1651739032,2655239241],\"stateMutability\":\"view\",\"type\":\"function\"},{"
    "\"conflictFields\":[{\"kind\":4,\"value\":[1]}],\"inputs\":[],\"name\":\"getString\","
    "\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"selector\":["
    "2313839663,167785564],\"stateMutability\":\"view\",\"type\":\"function\"},{\"conflictFields\":"
    "[{\"kind\":3,\"slot\":2,\"value\":[0]}],\"inputs\":[{\"internalType\":\"address\",\"name\":"
    "\"to\",\"type\":\"address\"},{\"internalType\":\"int256\",\"name\":\"count\",\"type\":"
    "\"int256\"}],\"name\":\"issue\",\"outputs\":[],\"selector\":[567142599,2699444860],"
    "\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"conflictFields\":[{\"kind\":4,"
    "\"value\":[0]},{\"kind\":4,\"value\":[1]}],\"inputs\":[],\"name\":\"logOut\",\"outputs\":[],"
    "\"selector\":[1273242286,2646634669],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}"
    ",{\"conflictFields\":[{\"kind\":4,\"value\":[0]}],\"inputs\":[],\"name\":\"returnRequire\","
    "\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"selector\":["
    "2153659808,2565523220],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{"
    "\"conflictFields\":[{\"kind\":4,\"value\":[0]}],\"inputs\":[],\"name\":\"returnRevert\","
    "\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"selector\":["
    "3705370812,3338033196],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{"
    "\"conflictFields\":[{\"kind\":4,\"value\":[0]}],\"inputs\":[{\"internalType\":\"int256\","
    "\"name\":\"value\",\"type\":\"int256\"}],\"name\":\"setInt\",\"outputs\":[],\"selector\":["
    "1953859256,4271946802],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{"
    "\"conflictFields\":[{\"kind\":4,\"value\":[1]}],\"inputs\":[{\"internalType\":\"string\","
    "\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setString\",\"outputs\":[],\"selector\":["
    "2144007782,1407179006],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{"
    "\"conflictFields\":[{\"kind\":3,\"slot\":2,\"value\":[0]},{\"kind\":3,\"slot\":2,\"value\":[1]"
    "}],\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{"
    "\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":"
    "\"int256\",\"name\":\"count\",\"type\":\"int256\"}],\"name\":\"transfer\",\"outputs\":[],"
    "\"selector\":[4254030087,1368843653],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}"
    "]";

bcos::bytes bcos::sample::getContractBin()
{
    bcos::bytes deployBin;
    boost::algorithm::unhex(HELLOWORLD_BYTECODE, std::back_inserter(deployBin));
    return deployBin;
}

std::string_view bcos::sample::getContractABI()
{
    return HELLOWORLD_ABI;
}

long bcos::sample::currentTime()
{
    return std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::steady_clock::now().time_since_epoch())
        .count();
}

bcos::sample::Collector::Collector(int count, std::string title)
  : m_startTime(currentTime()),
    m_count(count),
    m_title(std::move(title)),
    m_sendProgressBar{indicators::option::BarWidth{70}, indicators::option::ShowElapsedTime{true},
        indicators::option::ShowRemainingTime{true}, indicators::option::Start{"["},
        indicators::option::End{"]"}, indicators::option::ForegroundColor{indicators::Color::white},
        indicators::option::PostfixText{"Send   "},
        indicators::option::FontStyles{
            std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}},
    m_receiveProgressBar{indicators::option::BarWidth{70},
        indicators::option::ShowElapsedTime{true}, indicators::option::ShowRemainingTime{true},
        indicators::option::Start{"["}, indicators::option::End{"]"},
        indicators::option::ForegroundColor{indicators::Color::white},
        indicators::option::PostfixText{"Receive"},
        indicators::option::FontStyles{
            std::vector<indicators::FontStyle>{indicators::FontStyle::bold}}},
    m_progressBar{m_sendProgressBar, m_receiveProgressBar}
{
    indicators::show_console_cursor(false);
}
void bcos::sample::Collector::finishSend()
{
    sendElapsed = bcos::sample::currentTime() - m_startTime;
}
void bcos::sample::Collector::send(bool success, long elapsed)
{
    ++m_sended;
    while (m_sendProgressBar.current() < (size_t)(((double)m_sended / m_count) * 100.0))
    {
        m_progressBar.tick<0>();
    }
}
void bcos::sample::Collector::receive(bool success, long elapsed)
{
    ++m_finished;
    while (m_receiveProgressBar.current() < (size_t)(((double)m_finished / m_count) * 100.0))
    {
        m_progressBar.tick<1>();
    }
    if (!success)
    {
        ++m_failed;
    }
    m_allTimeCost += elapsed;
}
void bcos::sample::Collector::report()
{
    m_progressBar.print_progress();
    indicators::show_console_cursor(true);

    long receiveElapsed = bcos::sample::currentTime() - m_startTime;

    std::cout << std::endl << m_title << " done!" << std::endl;
    std::cout << "=======================================" << std::endl;
    std::cout << "Total received: " << m_finished << std::endl;
    std::cout << "Total failed: " << m_failed << std::endl;
    std::cout << "Receive elapsed: " << receiveElapsed << "ms" << std::endl;
    std::cout << "Avg time cost: " << ((double)m_allTimeCost.load() / (double)m_count) << "ms"
              << std::endl;
    std::cout << "Send TPS: " << ((double)m_count / (double)sendElapsed) * 1000.0 << std::endl;
    std::cout << "Receive TPS: " << ((double)m_count / (double)receiveElapsed) * 1000.0
              << std::endl;
}
std::string bcos::sample::parseRevertMessage(
    bcos::bytesConstRef output, bcos::crypto::Hash::Ptr hashImpl)
{
    auto data = output.getCroppedData(4);
    bcos::codec::abi::ContractABICodec abiCodec(*hashImpl);

    std::string message;
    abiCodec.abiOut(data, message);
    return message;
}
